package com.qdsg.modulesihealsdk.ecg12;


import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.hardware.usb.UsbManager;
import android.os.Environment;
import android.os.SystemClock;
import android.util.Log;

import com.example.moduleutils.LogUtil;
import com.qdsg.modulesihealsdk.entity.ECGResultEntity;
import com.qdsg.modulesihealsdk.utils.BitmapUtils;
import com.siheal.entitys.measure.ECGEntity;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;

import serial.jni.DataUtils;
import serial.jni.NativeCallBack;
import serial.jni.USBConnectionStateListener;

/**
 * @Description
 * @Author WuJianFeng
 * @Date 2022/11/21 16:32
 */
public class ECG12Utils {

    private ECG12Utils() {
    }

    private static volatile ECG12Utils instance;

    public static ECG12Utils getInstance() {
        if (instance == null) {
            synchronized (ECG12Utils.class) {
                if (instance == null) {
                    instance = new ECG12Utils();
                }
            }
        }

        return instance;
    }

    public final String oldVersion = "5.1.1";
    public String versionName;
    private UsbManager usbManager;
    private ECGEntity ecgEntity;
//    private Timer mTimer = null;

    private DataUtils mDataUtil;
    // 心电图
    private String strCase = "AECG";
    private ECG12Callback mECG12Callback;
    private Activity activity;
    private int mGain = DataUtils.DISPLAY_GAIN_5;
    private int mSpeed = DataUtils.DISPLAY_SPEED_10;
    private int mFilter = 4;
    Timer timer = null;
    private Timer detectTimer = null;
    /**
     * 心电数据队列
     */
    private ConcurrentLinkedQueue<Short> mEcgQueue;

    public void electrocaRdio(Activity activity, ECG12Callback mECG12Callback) {
        this.mECG12Callback = mECG12Callback;
        this.activity = activity;
        // 获取系统版本
        getAndroidSDKVersion();
        // 心电图  更新 UI  必须利用主线程方式
        if (oldVersion.equals(versionName)) {
            initEcg();
            return;
        }
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                initEcg();
            }
        });
    }

    /**
     * 设置增益
     */
    public void setGain(int gain) {
        mGain = gain;
        mDataUtil.setGain(mGain);
    }

    /**
     * 获取增益
     */
    public int getGain() {
        return mGain;
    }

    //设置走速
    public void setSpeed(int speed) {
        mSpeed = speed;
        mDataUtil.setSpeed(mSpeed);
    }

    /**
     * 获取走速
     */
    public int getSpeed() {
        return mSpeed;
    }

    //设置滤波
    public void setFiler(int filer) {
        mFilter = filer;
        mDataUtil.setFilter(mFilter);
    }

    /**
     * 获取滤波
     */
    public int getFiler() {
        return mFilter;
    }


    public String getAndroidSDKVersion() {
        try {
            versionName = android.os.Build.VERSION.RELEASE;
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.d("当前系统版本:", versionName);
        return versionName;
    }

    private void initEcg() {


        if (mECG12Callback != null) {
            mECG12Callback.judgeSystemVersion();
        }

        if (mDataUtil != null) {
            mEcgQueue = null;
            mDataUtil.gatherEnd();

        }
        if (mECG12Callback != null) {
            mECG12Callback.initView();
        }
        mDataUtil = null;
        usbManager = (UsbManager) activity.getSystemService(Context.USB_SERVICE);
        mDataUtil = new DataUtils(usbManager, new USBConnectionStateListener() {

            @Override
            public void OnUSBConnectionError(int state) {
                switch (state) {
                    case USBConnectionStateListener.ERROR_REMOVE_DEVICE:
                    case USBConnectionStateListener.ERROR_NO_USB_PERMISSION:
                    case USBConnectionStateListener.ERROR_INTERRUPTED:
                    case USBConnectionStateListener.ERROR_SETTING_DEVICE:
                    case USBConnectionStateListener.ERROR_OPEN_DEVICE:
                        break;
                }
            }

            @Override
            public void OnUSBConnectSuccess() {
            }

            @Override
            public void OnUSBConnectStart() {
            }

            @Override
            public void OnUSBConnectFaild() {
            }
        });
        // 初始化
        mDataUtil.setDisplayMode(DataUtils.DISPLAY_MODE_12x1);

        if (mECG12Callback != null) {
            mECG12Callback.initDisplay();
        }
        ecgEntity = new ECGEntity();

        if (mDataUtil != null) {
            // 连接设备
            //设置增益
            mDataUtil.setGain(mGain);
            //设置走速
            mDataUtil.setSpeed(mSpeed);
            //设置滤波
            mDataUtil.setFilter(mFilter);
            mDataUtil.gatherStart(new NativeMsg());
        }
        if (mECG12Callback != null) {
            mECG12Callback.startRenderer();
        }

        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                //execute the task
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mEcgQueue = new ConcurrentLinkedQueue<Short>();

                        if (mECG12Callback != null) {
                            mECG12Callback.updateUI(mEcgQueue);
                        }
                    }
                });
            }
        };
        timer = new Timer();
        timer.schedule(task, 500);
    }


    /**
     * 关闭心电
     */
    public void closeElectrocardio() {
        // 关闭心电
        try {
            if (mDataUtil != null) {
                mDataUtil.cancelCase();
                mDataUtil.gatherEnd();
                mDataUtil = null;
            }
            if (mECG12Callback != null) {
                mECG12Callback.closeElectrocardio();
            }
            if (mEcgQueue != null) {
                mEcgQueue = null;
            }
            if (usbManager != null) {
                usbManager = null;
            }
            if (ecgEntity != null) {
                ecgEntity = null;
            }
            if (instance != null) {
                instance = null;
            }
            if (mECG12Callback != null) {
                mECG12Callback = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    class NativeMsg extends NativeCallBack {

        @Override
        public void callHRMsg(short hr) {// 心率
            if (mECG12Callback != null) {
                mECG12Callback.setHr(hr);
            }
        }

        @Override
        public void callLeadOffMsg(String flagOff) {// 导联脱落
            LogUtil.logAndWrite("__ecg12-1","导联脱落");
        }

        @Override
        public void callProgressMsg(short progress) {// 文件存储进度百分比 progress%
        }

        @Override
        public void callCaseStateMsg(short state) {
            if (state == 0) {// 开始存储文件
                LogUtil.logAndWrite("__ecg12-2","开始存储文件 state = " + state);
            } else {// 存储完成
                LogUtil.logAndWrite("__ecg12-3","存储完成 state = " + state);
                timer.cancel();
                timer = null;
                detectTimer.cancel();
                detectTimer = null;
                analysisEcgData();
            }
        }

        private void analysisEcgData() {
            int i = mDataUtil.ecgDataToAECG(Environment.getExternalStorageDirectory() +
                            "/ecg/AECG_" + ecgEntity.getMeasureID() + ".c8k",
                    Environment.getExternalStorageDirectory() +
                            "/ecg/AECG_" + ecgEntity.getMeasureID() + ".xml");
            if (i == 1) {
                int ecgAnalyzeToXmlCode = mDataUtil.ecgAnalyzeToXml(
                        Environment.getExternalStorageDirectory() + "/ecg/"
                                + strCase + "_" + ecgEntity.getMeasureID(),
                        Environment.getExternalStorageDirectory() + "/ecg/"
                                + "/BECG_advice_" + ecgEntity.getMeasureID() + ".xml",
                        Environment.getExternalStorageDirectory()
                                + "/conclusion.cn");
                LogUtil.logAndWrite("__ecg12-4","心电ecgAnalyzeToXmlCode ：" + ecgAnalyzeToXmlCode);


                if (ecgAnalyzeToXmlCode == 1) {
                    LogUtil.logAndWrite("__ecg12-5","写入文件完成");
                    showReport();
                } else {
                    LogUtil.logAndWrite("__ecg12-6","写入文件完成 但没有文件");
                }
            } else {
                LogUtil.logAndWrite("__ecg12-7","写入文件 失败" + ecgEntity.getMeasureID());
            }
        }

        private void showReport() {

            //设置走速  文件问题
            if (getECGRootElement() == null || getECGRootElement().elements() == null) {
                return;
            }//报告数据不存在
            List<Element> elements = getECGRootElement().elements();
            for (Element e : elements) {
                if (e.getName().equals("Normal")) {
                    Iterator<Attribute> iterator = e.elements().get(0).attributeIterator();
                    while (iterator.hasNext()) {
                        Attribute attribute = iterator.next();
                        switch (attribute.getName()) {
                            case "HR":
                                ecgEntity.setHr(attribute.getValue());
                                break;
                            case "PDur":
                                ecgEntity.setPdur(attribute.getValue());
                                break;
                            case "TDur":
                                ecgEntity.setTdur(attribute.getValue());
                                break;
                            case "QTCDur":
                                ecgEntity.setQtcdur(attribute.getValue());
                                break;
                            case "PAxis":
                                try {
                                    float p = Float.parseFloat(attribute.getValue());
                                    ecgEntity.setPaxis(attribute.getValue());
                                } catch (Exception e1) {
                                }
                                break;
                            case "TAxis":
                                try {
                                    ecgEntity.setTaxis(attribute.getValue());
                                } catch (Exception e1) {
                                }
                                break;
                            case "PR":
                                ecgEntity.setPr(attribute.getValue());
                                break;
                            case "Rv5_Sv1_1":
                                ecgEntity.setRv5_sv1_1(attribute.getValue());
                                break;
                            case "Rv5_Sv1_2":
                                ecgEntity.setRv5_sv1_2(attribute.getValue());
                                break;
                            case "QRSDur":
                                ecgEntity.setQrsdur(attribute.getValue());
                                break;
                            case "QTDur":
                                ecgEntity.setQtdur(attribute.getValue());
                                break;
                            case "QRSAxis":
                                try {
                                    ecgEntity.setQrsaxis(attribute.getValue());
                                } catch (Exception e1) {
                                }
                                break;
                        }
                    }
                } else if (e.getName().equals("Advice")) {
                    ecgEntity.setAdvice(e.getStringValue());
                }
            }

            buildBitmap(Environment.getExternalStorageDirectory() + "/ecg/" + ecgEntity.getMeasureID() + ".png", ecgEntity);


        }

        public Element getECGRootElement() {
            File file = new File(Environment.getExternalStorageDirectory() + "/ecg/"
                    + "/BECG_advice_" + ecgEntity.getMeasureID() + ".xml");
            InputStream is = null;
            try {
                is = new FileInputStream(file);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                LogUtil.logAndWrite("__ecg12-8","FileNotFoundException-831-" + ecgEntity.getMeasureID());

            }

            SAXReader reader = new SAXReader();
            Document document = null;
            try {
                document = reader.read(is);
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
                LogUtil.logAndWrite("__ecg12-9","IOException-844-" + ecgEntity.getMeasureID());
                return null;
            }

            return document.getRootElement();
        }

        //aeccg 文件生成心电图片
        private void buildBitmap(String filePath, ECGEntity ecgEntity) {
            //path aecg.xml 文件存储地址
            short[] data = AECGParse.parseAECGRecord(new File(
                    Environment.getExternalStorageDirectory() + "/ecg/"
                            + "AECG_" + ecgEntity.getMeasureID() + ".xml"));
            if (data != null) {
                PngReport mPng = new PngReport(data);
                Bitmap mBitmap = mPng.getBitmap(filePath, String.valueOf(mGain), String.valueOf(mSpeed));
                //main 设置控件值
                ECGResultEntity ecgResultEntity = new ECGResultEntity(ecgEntity, BitmapUtils.byte2Base64(BitmapUtils.bitmap2Byte(mBitmap)), mBitmap);

                if (mECG12Callback != null) {
                    mECG12Callback.resultReceived(ecgResultEntity);
                }
            }
        }

        @Override
        public void callHBSMsg(short hbs) {// 心率 hbs = 1表示有心跳
            // Log.e("HeartBeat", "Sound"+hbs);
        }

        @Override
        public void callBatteryMsg(short per) {// 采集盒电量
            // Log.e("Battery", ""+per);
        }

        @Override
        public void callCountDownMsg(short per) {// 剩余存储时长
            // Log.e("CountDown", ""+per);
        }

        @Override
        public void callWaveColorMsg(boolean flag) {
            if (flag) {
                File dir = new File(Environment.getExternalStorageDirectory() + "/ecg/");
                if (!dir.exists()) {
                    dir.mkdir();
                }

                if (mECG12Callback != null) {
                    mECG12Callback.setRendererColor();
                    long baseTimer = SystemClock.elapsedRealtime();
                    TimerTask task1 = new TimerTask() {
                        @Override
                        public void run() {
                            int time = (int) ((SystemClock.elapsedRealtime() - baseTimer) / 1000);
                            String mm = new DecimalFormat("00").format(time % 3600 / 60);
                            String ss = new DecimalFormat("00").format(time % 60);
                            String timeFormat = mm + "分" + ss + "秒";
                            mECG12Callback.detectTime(timeFormat);
                        }
                    };
                    detectTimer = new Timer();
                    detectTimer.schedule(task1, 0,1000);
                }

                mDataUtil.saveCase(Environment.getExternalStorageDirectory() +
                                "/ecg/",
                        strCase + "_" + ecgEntity.getMeasureID(), 15);
            }
        }

        @Override
        public void callEcgWaveDataMsg(short[] wave) {
            if (mEcgQueue != null) {
                for (int i = 48; i < 60; i++) {
                    mEcgQueue.offer(wave[i]);
                }
            }
        }

        @Override
        public void callEcg18WaveDataMsg(short[] wave) {
            if (mEcgQueue != null) {
                for (int i = 72; i < 90; i++) {
                    mEcgQueue.offer(wave[i]);
                }
            }
        }

        @Override
        public void callNibpStateMsg(byte flag, byte type) {
            super.callNibpStateMsg(flag, type);
        }

        @Override
        public void callNibpResultMsg(short sys, short dia, short mea,
                                      short pr, byte err) {
            super.callNibpResultMsg(sys, dia, mea, pr, err);
            Log.e("callNibpResultMsg", "sys : " + sys + " dia : " + dia + " mea : " + mea);
            mDataUtil.BluNIBPConfirmCmd();
        }

        @Override
        public void callSpO2ResultMsg(short spo2, short pr, byte state) {
            super.callSpO2ResultMsg(spo2, pr, state);
            if (spo2 > 0) {
                Log.e("callSpO2ResultMsg", "spo2 : " + spo2 + "  pr : " + pr);
            }
        }

        @Override
        public void callNibpCuffMsg(short val) {
            super.callNibpCuffMsg(val);
            Log.e("callNibpCuffMsg", "cuff : " + val);
        }

        @Override
        public void callSpO2ConntectStateMsg(short state) {
            super.callSpO2ConntectStateMsg(state);
        }
    }
}
